dojo.provide("apt.CalendarDay");
dojo.require("apt.DataRow");
dojo.require("dijit._WidgetBase");
dojo.require("dijit._TemplatedMixin");
dojo.require("dijit.WidgetSet");

dojo.declare("apt.CalendarDay", [dijit._WidgetBase, dijit._TemplatedMixin], {
  templateString: dojo.cache('apt.templates', 'CalendarDay.html'),
  widgetsInTemplate:    true,
  
  date:                 "",
  formattedDate:        "",
  minHourElementWidth:  18, // Pixels
  baseClass:            "day",
  dayStart:             6,
  dayEnd:               20,
  hours:                "",
  pixelTime:            "",
  week:                 "",
  cache:                "",
  brain: 								"", //reference to PlanningTool Widget,
  resources: 						"",
  status: 							"",
  isShowing: 						false,
  isHidden: 						false,
  width:                100,
  
  
  constructor : function(data){
    this.inherited(arguments);
    dojo.safeMixin(this, data);

    this.status = { availabilityLoaded: false, reservationsLoaded: false };
		this.resources = {};
	
    this.dataRows = new dijit.WidgetSet();
    
    if (Object.prototype.toString.call(this.date) != "[object Date]"){
		  console.error('Invalid Date object passed to CalendarDay');
      this.date = new Date();
    }

    this.baseClass = (this.date.toISOString().substr(0, 10) == this.brain.today.toISOString().substr(0, 10)) ? 'day today' : 'day';

    this.formattedDate = this.date.getDayName().substr(0, 2) + " " + this.date.getDate() + "." + (this.date.getMonth() + 1) + ".";  

    if (this.date.getDay() == 1){
      this.week = "Week " + this.date.getWeek();
    }
                
    this.cache = { pixelsPerHour: -1 };
  },
    
  postCreate: function(){
  },
  
  startup: function() {
		if (this.isShowing){
      this.queryAvailabilitiesAndReservations();
		}
    this.resize();
  },
  	
	delete: function(){
    dojo.style(this.domNode, 'display', 'none');
		for (var key in this.resources) {
			if (this.resources.hasOwnProperty(key)){
				this.brain.removeResource(key);
			}
		};
		this.destroyRecursive();
	},
	
  isStillShowing: function(){
    // TODO: This errors out sometimes with ok consequenses;
     if (this.parent.domNode && this.domNode) {
        var pos = dojo.position(this.parent.domNode);
        var left = pos.x;
        var right = pos.x + pos.w;
        var epos = dojo.position(this.domNode);
        return (epos.x < right && epos.x + epos.w > left);
    } else {
        console.log("Can't get this.parent.domNode or this.domNode");
        return false;
    }
  },
	
	setShowing: function(){
		this.isHidden = false;
		if (!this.isShowing){
      this.isShowing = true;
      setTimeout(dojo.hitch(this, function(){ if(this.isStillShowing()) { 
        this.startup();
      } else { this.isShowing = false;}
    })
      , 500);
		};
	},

	setIsHidden: function(){
    this.isShowing = false;
		this.isHidden = true;
    // this.dataRows.forEach(function(w, i){ w.destroyRecursive(); });
	},
	
	queryAvailabilitiesAndReservations: function(){
		var dayEnd = this.dayEndAsDate().toISOString().substr(0, 10);
		var dayStart = this.dayStartAsDate().toISOString().substr(0, 10);
		dojo.when(
			this.brain.stores.availabilities.query({ 
        startDate: dayStart,
        endDate: dayStart
      }),
			dojo.hitch(this, function(result){ this.availabilityLoaded(result)} ),
			dojo.hitch(this, function(result){ this.availabilityLoadError(error)})			
		);
    
		dojo.when(
			this.brain.stores.reservations.query( { 
        startDate: dayStart + " 00:00",
        endDate: dayEnd + " 24:00"
    }),
			dojo.hitch(this, function(result){ this.reservationsLoaded(result)} ),
			dojo.hitch(this, function(result){ this.reservationsLoadError(error)})
		);
    
	},
	
	availabilityLoadError: function(error){
		console.log('Could not load availabilities for day', error);
	},

	reservationsLoadError: function(error){
		console.log('Could not load reservations for day', error);
	},
	
	availabilityLoaded: function(result){    
		if (result.length > 0){
			var t = this;
			result.forEach(function(e, i){
			  if (!t.resources.hasOwnProperty(e.SmanId)){
			  	t.brain.addResource(e.SmanId);
        }
        t.resources[e.SmanId] = t.resources[e.SmanId] || {};
        if (!t.resources[e.SmanId].hasOwnProperty('availabilities')) t.resources[e.SmanId].availabilities = []; 
        if (!t.resources[e.SmanId].hasOwnProperty('breaks')) t.resources[e.SmanId].breaks = [];
								
				if ( e.Type == t.brain.variables.break ) {
					t.resources[e.SmanId].breaks = t.resources[e.SmanId].breaks || [];
					t.resources[e.SmanId].breaks.push(e);
				} else if ( e.Type == t.brain.variables.work ) {
					t.resources[e.SmanId].availabilities = t.resources[e.SmanId].availabilities || [];
					t.resources[e.SmanId].availabilities.push(e);
				}

			});
		}
		this.status.availabilityLoaded = true;
		if (this.status.reservationsLoaded){
			this.renderDay();
		}
	},
	
	reservationsLoaded: function(result){     
		if (result.length > 0){
			var t = this;

      var dayEnd = new Date(this.date);
      dayEnd.setDate(this.date.getDate() + 1);

			result.forEach(function(e, i){
				dojo.forEach(e.Resources, function(r, ri){
          if (r.EndTime.parseISO8601() >= t.date && r.StartTime.parseISO8601() < dayEnd) {
    			  if (!t.resources.hasOwnProperty(r.ResourceId)){
    			  	t.brain.addResource(r.ResourceId);
            }
            var newReservation = {}
            newReservation.SmanId = r.ResourceId;
            newReservation.StartTimeJSDate = r.StartTime.parseISO8601();
            newReservation.EndTimeJSDate = r.EndTime.parseISO8601();
            newReservation.ReservationNumber = e.ReservationNumber;
            newReservation.ReservationInfo = e;

            // newReservation.Root = e;
            t.resources[r.ResourceId] = t.resources[r.ResourceId] || {};
            t.resources[r.ResourceId].reservations = t.resources[r.ResourceId].reservations || [];
            t.resources[r.ResourceId].reservations.push(newReservation);
          }
			  });
		  });
            // console.log('reservationsLoaded', result);      
		}
		this.status.reservationsLoaded = true;
		if (this.status.availabilityLoaded){
			this.renderDay();
		}		
	},
	
	renderDay: function(){
    var t = this;
    dojo.forEach(this.brain.resources, function(e, i){
      var dataForResource = {};
            
      // console.log(e.SmanId, t.resources[e.SmanId]);
      if (t.resources.hasOwnProperty(e.SmanId) && t.resources[e.SmanId].hasOwnProperty('availabilities') && t.resources[e.SmanId].availabilities.length > 0){
        dataForResource = t.resources[e.SmanId];
        /*
        if (t.resources[e.SmanId].hasOwnProperty('reservations')) {
          console.log(t.resources[e.SmanId].reservations);
        }
        */
      }      
      var row = new apt.DataRow( { resourceName: e.SmanId, parent: t, data: dataForResource } );
      t.dataRows.add(row);
      row.placeAt(t.dataRowsNode);
    })
	},
    
  dayLength: function(){
    var len = this.dayEnd - this.dayStart;
    if (len < 1){
      throw "Day length shouldn't be smaller than 1 hour";
    }
    return len;
  },  
  
  // createDataRowsForResources: function(){
  //     // Luo datarowt this.resources objectin order propertyn mukaisessa järjestyksessä;
  //     
  //   for (var i=0; i <  this.brain.calendarData.resources.length; i++) {
  //     var row = (new apt.DataRow( { resourceName: this.brain.calendarData.resources[i], parent: this } ));
  //     this.dataRows.add(row);
  //     row.placeAt(this.dataRowsNode);
  //   };    
  // },
  
  resize: function(viewPortSize) {
    this.resetPixelsPerHour();
    this.daysShowing = this.parent.daysShowing;
    
    if (typeof viewPortSize == 'undefined'){
      viewPortSize = dojo.position(this.parent.domNode).w;
    }
		
    var daySize = parseInt(viewPortSize / this.parent.daysShowing);
    dojo.style(this.domNode, 'width', daySize + "px");

		if (this.isShowing){
	    this.createHourElements();
	    this.dataRows.forEach(function(widget){
	        widget.resize();
	    });
		}
  },
  
  // updateHourElements: function(){
  //   var hourElementLength = (dojo.position(this.domNode).w -1) / this.hours.length <<0;
  //   dojo.map(this.hours, function(hour){
  //     dojo.style(hour, 'width', hourElementLength + "px");
  //   });
  // },
  
  createHourElements: function(){
    this.hourArea.innerHTML = '';
    this.hours = [];

    // Count maximum number of hour indicator elements that can be fitted to the widget
    var maxElements = dojo.position(this.domNode).w / this.minHourElementWidth;
    maxElements = maxElements|maxElements // Same as Math.floor() twice as fast;
    if (maxElements > this.dayLength()){
      maxElements = this.dayLength();
    }

    // Integer for how many hours long one hour indicator element must be
    var hourElementTimeSpan = Math.ceil(this.dayLength() / maxElements);

    // var elementWidth = 
    for (var i=this.dayStart; i < this.dayEnd; i = i + hourElementTimeSpan) {
      var hour = dojo.create("td", {innerHTML: '<div class="hour" style="margin: auto; width: 18px; text-align: center;">' + i + '</div>'});
      this.hours.push(hour);
      dojo.place(hour, this.hourArea);
    };
    
    // var hourElementLength = (dojo.position(this.domNode).w -2) / this.hours.length <<0;
    // dojo.map(this.hours, function(hour){
    //   dojo.style(hour, 'width', hourElementLength + "px");
    // });
    
    // dojo.style(this.domNode, 'width', hourElementLength * this.hours.length + 2 + "px");
  },
    
  getDataRowStartAndEnd: function(start, end){
    if (this.dayEnd < end){
      this.dayEnd = end;
    }
    if (this.dayStart > start){
      this.dayStart = start;
    }
  },
    
  dayEndAsDate: function(){    
    this.cache.dayEndAsDate = this.cache.dayEndAsDate || new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(), this.dayEnd);

    return this.cache.dayEndAsDate;
  },

  dayStartAsDate: function(){
    this.cache.dayStartAsDate = this.cache.dayStartAsDate || new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(), this.dayStart);

    return this.cache.dayStartAsDate;    
  },
  
  extractEventsForDay: function(item){
    return (item.StartTime.toDateFromAspNet() < this.dayEndAsDate() && item.EndTime.toDateFromAspNet() > this.dayStartAsDate());
  },

  extractAvailabilityForDay: function(item){
    var day = item.WorkingDay.toDateFromAspNet();
    return (item.Type == "Work" && day.getYear() == this.dayStartAsDate().getYear() && day.getMonth() == this.dayStartAsDate().getMonth() && day.getDate() == this.dayStartAsDate().getDate() );
  },

  extractBreaksForDay: function(item){
    var day = item.WorkingDay.toDateFromAspNet();
    return (item.Type == "Break" && day.getYear() == this.dayStartAsDate().getYear() && day.getMonth() == this.dayStartAsDate().getMonth() && day.getDate() == this.dayStartAsDate().getDate() );
  },

  getLeftOffsetForTime: function(hours, minutes){
    var o = this.getPixelsForHour(hours+(minutes/60)-this.dayStart);
    return o;
  },

  getRightOffsetForTime: function(hours, minutes){
    var o = this.getPixelsForHour(this.dayEnd-(hours+(minutes/60)));

    return o;
  },
  
  resetPixelsPerHour: function(){
    this.cache.pixelsPerHour = -1;
  },

  getPixelsForHour: function(hours){
    var pixelsPerHour = this.cache.pixelsPerHour;
    if (pixelsPerHour === -1){
      var pixels = dojo.position(this.domNode).w;
      pixelsPerHour = pixels / this.dayLength();
      this.cache.pixelsPerHour = pixelsPerHour;
    }
    return pixelsPerHour * hours;
  }  


});